<?php
// +----------------------------------------------------------------------
// | ZGUAN [ 致力于帮助更多的中小企业物联网转型 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.zguan.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ZGUAN 并不是自由软件，未经许可不能去掉ZGUAN 相关版权
// +----------------------------------------------------------------------
// | Author: ZGUAN Team <admin@zguan.cn>  0769-82282996  15899929162
// +----------------------------------------------------------------------
namespace app\common\repositories\energy;

use think\facade\Db;
use think\exception\ValidateException;
use app\common\repositories\BaseRepository;
use app\common\dao\energy\EnergySharedRoomDao;
use app\common\repositories\room\RoomBasicRepository;
use app\common\repositories\energy\EnergyMeterRepository;
use app\common\repositories\energy\EnergySharedLogsRepository;
use app\common\repositories\energy\EnergySharedPlanRepository;
use app\common\repositories\property\users\PropertyUsersLogRepository;
use app\common\repositories\property\auth\PropertyAuthAccessRepository;

/**
 * Class EnergySharedRoomRepository
 *
 * @mixin EnergySharedRoomDao
 */
class EnergySharedRoomRepository extends BaseRepository
{

    public function __construct(EnergySharedRoomDao $dao)
    {
        $this->dao = $dao;
    }

    public function getPropertyList(array $where, $page, $limit, int $propertyId = null)
    {
        $query = $this->dao->search($where, $propertyId);
        $count = $query->count();
        $list = $query->page($page, $limit)
            ->with([
                'roomInfo' => function ($query) {
                    $query->bind(['full_room_name']);
                },
            ])
            ->order('id', 'desc')
            ->select();
        return compact('count', 'list');
    }

    public function getApiList(array $where, $page, $limit, int $propertyId = null)
    {
        /** @var PropertyAuthAccessRepository $propertyAuthAccessRepository */
        $propertyAuthAccessRepository = app()->make(PropertyAuthAccessRepository::class);
        $propertyIds = $propertyAuthAccessRepository->getPropertyIdsByUserId($where['add_uid']);
        $query = $this->dao->search($where, $propertyId)
            ->where(function ($query) use ($where, $propertyIds) {
                ## 授权物业
                $query->where('property_id', 'in', $propertyIds);
            });
        $count = $query->count();
        $list = $query->page($page, $limit)
            ->with([
                'roomInfo' => function ($query) {
                    $query->bind(['full_room_name']);
                }
            ])
            ->order('id', 'desc')
            ->hidden(['property_id', 'property_id', 'edit_time'])
            ->select();
        return compact('count', 'list');
    }

    public function getApiNoRoomList(array $where = [])
    {
        $roomIds = $this->dao->getSearch([])
            ->where('plan_id', $where['plan_id'])
            ->column('room_id');
        /** @var RoomBasicRepository $roomBasicRepository */
        $roomBasicRepository = app()->make(RoomBasicRepository::class);
        $list = $roomBasicRepository->getSearch([])
            ->where('property_id', $where['property_id'])
            ->where('id', 'not in', $roomIds)
            ->append(['unit_room_name'])
            ->visible(['unit_room_name', 'id'])
            ->hidden(['propertyInfo'])
            ->select()->toArray();
        return compact('list');
    }


    public function addInfo(array $data, int $propertyId, int $userId)
    {
        return Db::transaction(function () use ($data, $propertyId, $userId) {

            $data['property_id'] = $propertyId;
            $info = $this->dao->create($data);
            /** @var PropertyUsersLogRepository $repository */
            $repository = app()->make(PropertyUsersLogRepository::class);
            $repository->addInfo($propertyId, $userId, 'SHARED.ENERGY.ROOM.ADD', $data);
            return $info;
        });
    }


    public function editInfo($info, array $data, int $userId = 0)
    {
        return Db::transaction(function () use ($data, $info, $userId) {
            if (isset($data['stair_price']) && is_array($data['stair_price'])) {
                $data['stair_price'] = json_encode($data['stair_price'], JSON_UNESCAPED_UNICODE);
            }
            /** @var PropertyUsersLogRepository $repository */
            $repository = app()->make(PropertyUsersLogRepository::class);
            $repository->addInfo($info['property_id'], $userId, 'SHARED.ENERGY.ROOM.EDIT', $data);
            return $this->dao->update($info['id'], $data);
        });
    }

    public function getDetail(int $id)
    {
        $data = $this->dao->search([])
            ->where('id', $id)
            ->find();
        return $data;
    }

    public function batchDelete(array $ids, int $userId = 0)
    {
        $list = $this->dao->selectWhere([
            ['id', 'in', $ids]
        ]);
        if ($list) {
            foreach ($list as $k => $v) {
                $this->deleteInfo($v, $userId);
            }
            return $list;
        }
        return [];
    }

    public function deleteInfo($info, int $userId = 0)
    {
        return Db::transaction(function () use ($info, $userId) {
            /** @var PropertyUsersLogRepository $repository */
            $repository = app()->make(PropertyUsersLogRepository::class);
            $repository->addInfo($info['property_id'], $userId, 'SHARED.ENERGY.ROOM.DEL', $info);

            ## 删除关联房间公摊日志
            /** * @var EnergySharedLogsRepository $energySharedLogsRepository */
            $energySharedLogsRepository = app()->make(EnergySharedLogsRepository::class);
            $energySharedLogsRepository->removeSharedRoomId($info['id']);

            $this->dao->delete($info['id']);
        });
    }


    /**
     * 方案配置
     * @param array $schemeInfo 方案信息
     * @param array $data
     * @return mixed
     */
    public function schemeConfig($planInfo, array $data, int $userId = 0)
    {
        $roomData = convert_arr_key($data['room'], 'room_id');
        $roomIds = get_arr_column($roomData, 'room_id');
        /** @var RoomBasicRepository $roomBasicRepository */
        $roomBasicRepository = app()->make(RoomBasicRepository::class);
        $roomList = $roomBasicRepository->getSearch([])
            ->where('property_id', $planInfo['property_id'])
            ->where('id', 'in', $roomIds)
            ->column('room_name,property_id', 'id');
        if (!$roomList) {
            throw new ValidateException('房间数据不存在');
        }
        foreach ($roomList as $k => $v) {
            $roomList[$k]['scale'] = $roomData[$v['id']]['scale'] ?? 0;
        }
        return Db::transaction(function () use ($planInfo, $roomIds, $roomList, $data, $userId) {
            $oldRoomData = $this->dao->getSearch([])
                ->where('plan_id', $planInfo['id'])
                ->column('scale,id', 'room_id');
            foreach ($roomList as $k => $v) {
                if (!isset($oldRoomData[$v['id']])) { // 不存在新增
                    $this->dao->create([
                        'property_id' => $planInfo['property_id'],
                        'energy_id' => $planInfo['energy_id'],
                        'property_id' => $v['property_id'],
                        'plan_id' => $planInfo['id'],
                        'start_date' => date("Y-m-d"),
                        'room_id' => $v['id'],
                        'scale' => $v['scale'],
                        'is_settle' => 1,
                    ]);
                }
            }
            /** @var PropertyUsersLogRepository $repository */
            $repository = app()->make(PropertyUsersLogRepository::class);
            $repository->addInfo($planInfo['property_id'], $userId, 'SHARED.ENERGY.ROOM.SCHEME');
            return true;
        });
    }

    ## 均摊方案执行


    /**
     * 用量分配
     * @param int $energyId
     * @return false|void
     *
     * @author Amos
     * 2024-05-14 11:10
     */
    public function usageAllocation(int $energyId, $remark = '')
    {
        /** @var EnergyMeterRepository $energyMeterRepository */
        $energyMeterRepository = app()->make(EnergyMeterRepository::class);
        // 计算公摊用量
        $emergrMeterInfo = $energyMeterRepository->get($energyId);
        if ($emergrMeterInfo) {
            /** @var EnergySharedPlanRepository $energySharedPlanRepository */
            $energySharedPlanRepository = app()->make(EnergySharedPlanRepository::class);
            $sharedPlanInfo = $energySharedPlanRepository->getSearch([])
                ->where('energy_id', $energyId)
                ->where('energy_type', $emergrMeterInfo['energy_type'])
                ->where('property_id', $emergrMeterInfo['property_id'])
                ->find();
            if ($sharedPlanInfo) {
                $chargingRoomList = $this->dao->getSearch([])
                    ->where('property_id', $emergrMeterInfo['property_id'])
                    ->where('energy_id', $emergrMeterInfo['id'])
                    ->where('is_settle', 1)
                    ->select()->toArray();
                $chargingRoomList = convert_arr_key($chargingRoomList, 'room_id');
                $roomIds = get_arr_column($chargingRoomList, 'room_id');

                /** @var RoomBasicRepository $roomBasicRepository */
                $roomBasicRepository = app()->make(RoomBasicRepository::class);
                ## 查询已出租的房间
                $roomList = $roomBasicRepository->getSearch([])
                    ->where('id', 'in', $roomIds)
                    ->where('status', 2)
                    ->field('id,room_size')
                    ->select()->toArray();
                if (!$roomList) {
                    return false;
                }
                $beilv = $emergrMeterInfo['beilv'];
                $use_num_z = bcmul(bcsub($emergrMeterInfo['read_z'], $emergrMeterInfo['base_z'], 4), $beilv, 4);
                $use_num_j = bcmul(bcsub($emergrMeterInfo['read_j'], $emergrMeterInfo['base_j'], 4), $beilv, 4);
                $use_num_f = bcmul(bcsub($emergrMeterInfo['read_f'], $emergrMeterInfo['base_f'], 4), $beilv, 4);
                $use_num_p = bcmul(bcsub($emergrMeterInfo['read_p'], $emergrMeterInfo['base_p'], 4), $beilv, 4);
                $use_num_g = bcmul(bcsub($emergrMeterInfo['read_g'], $emergrMeterInfo['base_g'], 4), $beilv, 4);
                if ($use_num_z <= 0) {
                    return false;
                }
                /** @var EnergySharedLogsRepository $energySharedLogsRepository */
                $energySharedLogsRepository = app()->make(EnergySharedLogsRepository::class);

                $pfUseNumZ = $pfUseNumJ = $pfUseNumF = $pfUseNumP = $pfUseNumG = 0.00;
                if ($sharedPlanInfo['plan_type'] == 1) { ## 计费方案：按面积计算
                    ## 房间总面积
                    $totalSize = array_sum(get_arr_column($roomList, 'room_size'));
                    ## 每平方分得用量
                    $sizeUseNumZ = bcdiv($use_num_z, $totalSize, 10);
                    $sizeUseNumJ = bcdiv($use_num_j, $totalSize, 10);
                    $sizeUseNumF = bcdiv($use_num_f, $totalSize, 10);
                    $sizeUseNumP = bcdiv($use_num_p, $totalSize, 10);
                    $sizeUseNumG = bcdiv($use_num_g, $totalSize, 10);

                    foreach ($roomList as $v) {
                        $chargingRoomInfo = $chargingRoomList[$v['id']];
                        if (isset($chargingRoomList[$v['id']])) {
                            $countUseNumLogs['use_num_z'] = $pfUseNumZ = bcmul($sizeUseNumZ, $v['room_size'], 8);
                            $countUseNumLogs['use_num_j'] = $pfUseNumJ = bcmul($sizeUseNumJ, $v['room_size'], 8);
                            $countUseNumLogs['use_num_f'] = $pfUseNumF = bcmul($sizeUseNumF, $v['room_size'], 8);
                            $countUseNumLogs['use_num_p'] = $pfUseNumP = bcmul($sizeUseNumP, $v['room_size'], 8);
                            $countUseNumLogs['use_num_g'] = $pfUseNumG = bcmul($sizeUseNumG, $v['room_size'], 8);
                            $this->dao->update($chargingRoomInfo['id'], [
                                'use_num_z' => bcadd($pfUseNumZ, $chargingRoomInfo['use_num_z'], 8),
                                'use_num_j' => bcadd($pfUseNumJ, $chargingRoomInfo['use_num_j'], 8),
                                'use_num_f' => bcadd($pfUseNumF, $chargingRoomInfo['use_num_f'], 8),
                                'use_num_p' => bcadd($pfUseNumP, $chargingRoomInfo['use_num_p'], 8),
                                'use_num_g' => bcadd($pfUseNumG, $chargingRoomInfo['use_num_g'], 8),
                            ]);
                            ## 添加日志
                            if (isset($remark)) {
                                $countUseNumLogs['remark'] = $remark;
                            }
                            $countUseNumLogs['property_id'] = $sharedPlanInfo['property_id'];
                            $countUseNumLogs['shared_plan_id'] = $sharedPlanInfo['id'];
                            $countUseNumLogs['shared_room_id'] = $chargingRoomInfo['id'];
                            $countUseNumLogs['energy_id'] = $chargingRoomInfo['energy_id'];
                            $countUseNumLogs['property_id'] = $chargingRoomInfo['property_id'];
                            $energySharedLogsRepository->create($countUseNumLogs);
                        }
                    }
                }

                if ($sharedPlanInfo['plan_type'] == 2 && $sharedPlanInfo['is_type'] == 1) { ## 计费方案：按比例  平分计算
                    $roomNum = count($roomList);
                    $countUseNumLogs['use_num_z'] = $pfUseNumZ = bcdiv($use_num_z, $roomNum, 8);
                    $countUseNumLogs['use_num_j'] = $pfUseNumJ = bcdiv($use_num_j, $roomNum, 8);
                    $countUseNumLogs['use_num_f'] = $pfUseNumF = bcdiv($use_num_f, $roomNum, 8);
                    $countUseNumLogs['use_num_p'] = $pfUseNumP = bcdiv($use_num_p, $roomNum, 8);
                    $countUseNumLogs['use_num_g'] = $pfUseNumG = bcdiv($use_num_g, $roomNum, 8);
                    foreach ($roomList as $v) {
                        $chargingRoomInfo = $chargingRoomList[$v['id']];
                        $this->dao->update($chargingRoomInfo['id'], [
                            'use_num_z' => bcadd($pfUseNumZ, $chargingRoomInfo['use_num_z'], 8),
                            'use_num_j' => bcadd($pfUseNumJ, $chargingRoomInfo['use_num_j'], 8),
                            'use_num_f' => bcadd($pfUseNumF, $chargingRoomInfo['use_num_f'], 8),
                            'use_num_p' => bcadd($pfUseNumP, $chargingRoomInfo['use_num_p'], 8),
                            'use_num_g' => bcadd($pfUseNumG, $chargingRoomInfo['use_num_g'], 8),
                        ]);
                        ## 添加日志
                        if (isset($remark)) {
                            $countUseNumLogs['remark'] = $remark;
                        }
                        $countUseNumLogs['property_id'] = $sharedPlanInfo['property_id'];
                        $countUseNumLogs['shared_plan_id'] = $sharedPlanInfo['id'];
                        $countUseNumLogs['shared_room_id'] = $chargingRoomInfo['id'];
                        $countUseNumLogs['energy_id'] = $chargingRoomInfo['energy_id'];
                        $countUseNumLogs['property_id'] = $chargingRoomInfo['property_id'];
                        $energySharedLogsRepository->create($countUseNumLogs);
                    }
                }

                if ($sharedPlanInfo['plan_type'] == 2 && $sharedPlanInfo['is_type'] == 2) { ## 计费方案：按比例 固定比例分配
                    foreach ($roomList as $v) {
                        $chargingRoomInfo = $chargingRoomList[$v['id']];
                        if (isset($chargingRoomList[$v['id']])) {
                            $countUseNumLogs['use_num_z'] = $pfUseNumZ = bcmul($use_num_z, $chargingRoomList[$v['id']]['scale'] / 100, 8);
                            $countUseNumLogs['use_num_j'] = $pfUseNumJ = bcmul($use_num_j, $chargingRoomList[$v['id']]['scale'] / 100, 8);
                            $countUseNumLogs['use_num_f'] = $pfUseNumF = bcmul($use_num_f, $chargingRoomList[$v['id']]['scale'] / 100, 8);
                            $countUseNumLogs['use_num_p'] = $pfUseNumP = bcmul($use_num_p, $chargingRoomList[$v['id']]['scale'] / 100, 8);
                            $countUseNumLogs['use_num_g'] = $pfUseNumG = bcmul($use_num_g, $chargingRoomList[$v['id']]['scale'] / 100, 8);
                            $this->dao->update($chargingRoomInfo['id'], [
                                'use_num_z' => bcadd($pfUseNumZ, $chargingRoomInfo['use_num_z'], 8),
                                'use_num_j' => bcadd($pfUseNumJ, $chargingRoomInfo['use_num_j'], 8),
                                'use_num_f' => bcadd($pfUseNumF, $chargingRoomInfo['use_num_f'], 8),
                                'use_num_p' => bcadd($pfUseNumP, $chargingRoomInfo['use_num_p'], 8),
                                'use_num_g' => bcadd($pfUseNumG, $chargingRoomInfo['use_num_g'], 8),
                            ]);
                            ## 添加日志
                            if (isset($remark)) {
                                $countUseNumLogs['remark'] = $remark;
                            }
                            $countUseNumLogs['property_id'] = $sharedPlanInfo['property_id'];
                            $countUseNumLogs['shared_plan_id'] = $sharedPlanInfo['id'];
                            $countUseNumLogs['shared_room_id'] = $chargingRoomInfo['id'];
                            $countUseNumLogs['energy_id'] = $chargingRoomInfo['energy_id'];
                            $countUseNumLogs['property_id'] = $chargingRoomInfo['property_id'];
                            $energySharedLogsRepository->create($countUseNumLogs);
                        }
                    }
                }

            }
            ## 更新结算数据
            $energyMeterRepository->update($emergrMeterInfo['id'], [
                'base_z' => $emergrMeterInfo['read_z'],
                'base_j' => $emergrMeterInfo['read_j'],
                'base_f' => $emergrMeterInfo['read_f'],
                'base_p' => $emergrMeterInfo['read_p'],
                'base_g' => $emergrMeterInfo['read_g'],
                'base_date' => date("Y-m-d")
            ]);
        }
    }


    /**
     * 验证设备管理权限
     * @param int $id
     * @param $userId
     * @return bool
     * @throws \think\db\exception\DbException
     *
     * @author Amos
     * 2024-05-18 17:22
     */
    public function existsByUserId(int $id, $userId)
    {
        return $this->dao->search([])
                ->where(function ($query) use ($userId) {
                    /** @var PropertyAuthAccessRepository $propertyAuthAccessRepository */
                    $propertyAuthAccessRepository = app()->make(PropertyAuthAccessRepository::class);
                    $propertyIds = $propertyAuthAccessRepository->getPropertyIdsByUserId($userId);
                    ## 验证权限
                    $query->where('property_id', 'in', $propertyIds);
                })->where('id', $id)->count() > 0;
    }
}